#include "World.h"
#include "Point2D.h"
#include "ImageBitmap.h"
#include <algorithm>
#include <math.h>
#include "StdAfx.h"



namespace HW2
{
	World::World()
	{
		isPerspective = false;
		BackgroundColor = Color(255,255,255);
		id =0;
		
		filterSize = 3;
		filterType = 0;
		init();


	}

	void World::reset()
	{
		polygons.clear();
		edges.clear();
		normals.clear();
		boundingBox.clear();
		polygonsNormals.clear();
		polygons.clear();
		init();
		id = 0;
	}

	void World::init()
	{
		double inf = 1<<30;
		minPoint = Coordinates( inf,  inf,  inf);
		maxPoint = Coordinates(-inf, -inf, -inf);
	}

	void World::addPolygon(Polygon &p)
	{
		
		polygons.push_back(p);

		polygons[polygons.size() -1 ].serialNum = id;//PAVEL
		id ++;//PAVEL

		int size = p.coordinates.size();

		//TRACE("----------------------------------------\n");

		for(int i = 0; i < size; i++)
		{
			//TRACE("%5lf %5lf %5lf\n",p.coordinates[i].X(), p.coordinates[i].Y(), p.coordinates[i].Z());

			edges.push_back(Edge(p.coordinates[i], p.coordinates[(i+1)%size], p.color));

			void* t = &(polygons[polygons.size() -1 ]);
			//edges[edges.size() - 1].parent = &(polygons[polygons.size() -1 ]); //PAVEL
			edges[edges.size() - 1].parentId = polygons.size() -1; 
			polygons[polygons.size() -1 ].edgeList.push_back(edges.size() - 1);//PAVEL


			double x = p.coordinates[i].X();
			double y = p.coordinates[i].Y();
			double z = p.coordinates[i].Z();
			minPoint.X() = min(x, minPoint.X());
			maxPoint.X() = max(x, maxPoint.X());
			minPoint.Y() = min(y, minPoint.Y());
			maxPoint.Y() = max(y, maxPoint.Y());
			minPoint.Z() = min(z, minPoint.Z());
			maxPoint.Z() = max(z, maxPoint.Z());
		}
	}

	void World::finishConstruction()
	{

		// Center the object on (0,0,0)
		Coordinates diff = maxPoint - minPoint;
		Coordinates offset = (Coordinates(0,0,0) - minPoint) - (diff/2);

		for(unsigned i = 0; i < edges.size(); i++)
		{
			edges[i].start += offset;
			edges[i].end += offset;
		}
		for(unsigned i = 0; i < polygons.size(); i++)
			for(unsigned j = 0; j < polygons[i].coordinates.size(); ++j)
				polygons[i].coordinates[j] += offset;

		maxPoint = diff / 2;
		minPoint = maxPoint - diff;

		initialRatio = diff.Y() / diff.X();


		////////////////////////////////////////////////////////////////////////
		///////////  Bounding box computation //////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		Coordinates dx = Coordinates(diff.X(),0,0);
		Coordinates dy = Coordinates(0,diff.Y(),0);
		Coordinates dz = Coordinates(0,0,diff.Z());

		Coordinates A = minPoint;
		Coordinates B = minPoint + dx;
		Coordinates C = minPoint + dx + dy;
		Coordinates D = minPoint + dy;

		Coordinates E = minPoint + dz;
		Coordinates F = E + dx;
		Coordinates G = E + dx + dy;
		Coordinates H = E + dy;

		Color red(255,0,0);
		boundingBox.push_back(Edge(A, B, red)); 
		boundingBox.push_back(Edge(B, C, red)); 
		boundingBox.push_back(Edge(C, D, red)); 
		boundingBox.push_back(Edge(D, A, red)); 

		boundingBox.push_back(Edge(E, F, red)); 
		boundingBox.push_back(Edge(F, G, red)); 
		boundingBox.push_back(Edge(G, H, red)); 
		boundingBox.push_back(Edge(H, E, red)); 

		boundingBox.push_back(Edge(A, E, red)); 
		boundingBox.push_back(Edge(B, F, red)); 
		boundingBox.push_back(Edge(C, G, red)); 
		boundingBox.push_back(Edge(D, H, red)); 

		////////////////////////////////////////////////////////////////////////
		///////////  Normals computation ///////////////////////////////////////
		////////////////////////////////////////////////////////////////////////

		// A hundreth of the diagonal
		Color normalColor = Color(0,255,0);
		double normalLength = sqrt(diff.X()*diff.X() + diff.Y()*diff.Y() + diff.Z()*diff.Z()) / 100;

		for(unsigned i = 0; i < polygons.size(); ++i)
		{
			for(unsigned j = 0; j < polygons[i].coordinates.size(); ++j)
			{
				Normal &n = polygons[i].normals[j];
				if(n.exists)
					normals.push_back(n.computeEdge(polygons[i].coordinates[j], normalLength, normalColor));
			}
		}

		////////////////////////////////////////////////////////////////////////
		///////////  Normals of Polygons ///////////////////////////////////////
		////////////////////////////////////////////////////////////////////////

		for(unsigned i = 0; i < polygons.size(); ++i)
		{
			Normal &n = polygons[i].normal;
			if(n.exists)
			{
				polygonsNormals.push_back(n.computeEdge(polygons[i].center(), normalLength, normalColor));
			}
		}
	}

	ImageBitmap* World::getPolygonByPoint2(int px, int py)
	{

		Point2D p(px,py);
		ImageBitmap *bitmapProbable = 0;
		for(int i = bitmaps.size() - 1; i >= 0; --i)
		{
			if(bitmaps[i].inside(p))
			{	// sorted by z
				bitmapProbable = &(bitmaps[i]);
				//bitmapProbable->p->color = Color(0,255,0);
				return bitmapProbable;
			}
		}
		return 0;
	}

	//=====================================PAVEL=====================================================



	int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
	{
		int i, j, c = 0;
		for (i = 0, j = nvert-1; i < nvert; j = i++) {
			if ( ((verty[i]>testy) != (verty[j]>testy)) &&
				(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
				c = !c;
		}
		return c;
	}

	//=============================================================================================
}

